import { _decorator, CCFloat, Collider, Component, Node, RigidBody, SkeletalAnimation, v3, Vec3 } from 'cc';
import { StateDef } from '../config/StateDefine';
import { MathUtil } from '../config/Utils';
const { ccclass, property } = _decorator;

const tempVelocity = v3()
@ccclass('Actor')
export class Actor extends Component {
    @property(SkeletalAnimation)
    private skeletalAnimation: SkeletalAnimation = null

    @property(CCFloat)
    private linearSpeed: number = 1.0

    @property(CCFloat)
    private angleSpeed: number = 10.0

    private currentState: StateDef = StateDef.Idle
    private rigidBody: RigidBody = null
    private collider: Collider = null
    public input: Vec3 = v3()

    start() {
        this.rigidBody = this.node.getComponent(RigidBody)
        this.collider = this.node.getComponent(Collider)
    }

    update(deltaTime: number) {
        switch (this.currentState) {
            case StateDef.Run:
                this.rotate()
                this.move()
                break
        
            default:
                break
        }
    }

    private move() {
        // 速度 = 方向（node.forward） * 基础速度 * 因子（摇杆输入的长度（加速、减速等））
        const speed = this.input.length() * this.linearSpeed

        tempVelocity.x = this.node.forward.x * speed
        tempVelocity.y = 0
        tempVelocity.z = this.node.forward.z * speed
        
        console.log(tempVelocity)
        this.rigidBody.setLinearVelocity(tempVelocity)
        // this.node.forward = this.input
    }

    private stopMove() {
        this.rigidBody.setLinearVelocity(Vec3.ZERO)
    }

    private rotate() {
        // 如果直接让 this.node.forward = this.input，会让动画比较生硬，
        // 旋转，输入方向和当前朝向的夹角，旋转的方向只会沿着Y轴方向旋转，所以x、z都为0
        // y 等于基础速度 * 因子，因子就是当前角色朝向和输入方向的夹角
        tempVelocity.x = 0
        tempVelocity.z = 0

        const angle = MathUtil.signAngle(this.node.forward, this.input, Vec3.UP)
        tempVelocity.y = angle * this.angleSpeed

        this.rigidBody.setAngularVelocity(tempVelocity)
    }

    public changeState(destState: StateDef) {
        if (this.currentState === StateDef.Die) return

        if (this.currentState === StateDef.Hit) {
            if (destState !==StateDef.Die && destState !== StateDef.Hit) {
                return
            }
        }

        if (this.currentState !== StateDef.Run) {
            this.stopMove()
        }

        this.currentState = destState
        // console.log(destState)
        this.skeletalAnimation.crossFade(destState, 0.3)
    }

    private respawn() {
        this.currentState = StateDef.Idle
        this.skeletalAnimation.crossFade(this.currentState, 0.3)
    }
}


